package com.net.xpay.core.service.impl;

import com.net.xpay.common.domain.User;
import com.net.xpay.core.constant.PoseidonErrorCode;
import com.net.xpay.core.validator.UserAccountValidator;
import com.net.common.annotation.WriteTransactional;
import com.net.common.exception.BusinessException;
import com.net.xpay.core.domain.AccountDetail;
import com.net.xpay.core.domain.AccountLog;
import com.net.xpay.core.domain.UserAccount;
import com.net.xpay.core.enums.AccountFundType;
import com.net.xpay.core.enums.PayStatus;
import com.net.xpay.core.manager.AccountDetailManager;
import com.net.xpay.core.manager.AccountLogManager;
import com.net.xpay.core.manager.UserAccountManager;
import com.net.xpay.core.service.AccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
 * 2020/5/11 11:57

 */
@Slf4j
@Service
@WriteTransactional
public class AccountServiceImpl implements AccountService {

    @Autowired
    private UserAccountValidator userAccountValidator;

    @Autowired
    private AccountDetailManager accountDetailManager;

    @Autowired
    private UserAccountManager userAccountManager;

    @Autowired
    private AccountLogManager accountLogManager;

    @Override
    public void onPay(User user, UserAccount account, AccountDetail detail) {
        userAccountValidator.validateAccountEnough(account, detail);

        onFinishAccountPay(user, account, detail);
    }

    private void onFinishAccountPay(User user, UserAccount account, AccountDetail detail) {
        detail.setPayStatus(PayStatus.PAYED);
        detail.setEndTime(LocalDateTime.now());
        accountDetailManager.save(detail);

        AccountLog accountLog = AccountLog.getInstance(user, detail);
        accountLog.setChange(detail.getChange());

        if (AccountFundType.MONEY.equals(detail.getAccountFundType())) {
            accountLog.setBeforeAmount(account.getMoneyLeft());
            accountLog.setAfterAmount(account.getMoneyLeft() + detail.getChange());

            account.setMoneyLeft(account.getMoneyLeft() + detail.getChange());
        } else if (AccountFundType.TRANS_BATCH.equals(detail.getAccountFundType())) {
            account.setTransBatchLeft(account.getTransBatchLeft() + detail.getChange());
        } else {
            throw new BusinessException(PoseidonErrorCode.UNKNOWN_ERROR, "未知的资金类型！");
        }

        accountLogManager.save(accountLog);

        userAccountManager.updateByPrimaryKeyWithVersion(account);
    }
}
